package com.eyedsion.his.web.service;

import com.eyedsion.his.web.dao.his.MyBatisBaseMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.repository.JpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Table;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CountDownLatch;

/**
 * @author 彭长云
 * @Description:
 * @date 2018/12/18 17:31
 */
public class TestService<T, ID extends Serializable> {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private EntityManagerFactory entityManagerFactory;
    @Autowired
    private EntityManager entityManager;
    @Autowired
    private JpaRepository<T, Serializable> baseRepository;
    @Autowired
    private MyBatisBaseMapper<T> baseMapper;
    @Value("${syncdata.init}")
    private boolean isInit;
    @Value("${syncdata.pagehelper.pageSize}")
    private Integer pageSize;

    private List<T> resultList;

    public void testThreadSyncData() {
        try {
            resultList = baseMapper.findAll();
            logger.info("开始同步表:" + getClazz().getAnnotation(Table.class).name());
            logger.info("查询到数据条数:" + resultList.size());
            deleteAll();
            logger.info("删除历史数据成功");

            final CountDownLatch latch = new CountDownLatch(10);
            for(int i=0;i<10;i++){
                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        testinsert(null);
                        latch.countDown();
                    }
                },"线程--" +i);
                t.start();
            }
            latch.await();
            logger.info("同步数据完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void testinsert(List<T> listEntity) {
        int batchSize = 500;
        ListIterator<T> iterator = resultList.listIterator();
        int i = 0;
        EntityManager em = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        transaction.begin();
        //记录所有的错误的数据
        List<T> errList = new ArrayList<>();
        //记录错误批次的数据
        List<T> batchList = new ArrayList<>();
        try {
            while (iterator.hasNext()) {
                try {
                    T entity = null;
                    synchronized (resultList) {
                        int listSize = resultList.size();
                        if (listSize == 0) {
                            break;
                        }
                        int maxLen = listSize - 1;
                        entity = resultList.get(maxLen);
                        resultList.remove(maxLen);
                    }

                    batchList.add(entity);
                    em.persist(entity);

                    if (i++ > 0 && i % batchSize == 0) {
                        em.flush();
                        em.clear();

                        transaction.commit();
                        transaction.begin();
                        batchList.clear();
                    }
                } catch (Exception e) {
                    //多线程记录错误信息位置?
                    e.printStackTrace();
                    errList.addAll(batchList);
                    batchList.clear();
                    transaction.rollback();
                    transaction.begin();
                }
            }
            transaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
            transaction.rollback();
            errList.addAll(batchList);
        }
        if (entityManager.isOpen()) {
            entityManager.close();
        }
    }

    /**
     *
     *@author： 彭长云
     * @Description:删除dec库对应历史数据，全部删除
     * @date： 2018/12/13 9:30
     * @param： []
     * @return： void
     */
    private void deleteAll() {
        baseRepository.deleteAllInBatch();
    }

    private Class<T> getClazz() {
        Class<T> clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return clazz;
    }


}
